package com.kexilo.exception.monitor;

import com.kexilo.exception.domain.ExceptionRecord;
import com.kexilo.exception.service.ExceptionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import jakarta.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 异常监控器
 * 负责记录和监控系统异常
 * 
 * @author Kexilo
 */
@Component
public class ExceptionMonitor {
    
    private static final Logger log = LoggerFactory.getLogger(ExceptionMonitor.class);
    
    /**
     * 异常计数器
     */
    private final AtomicLong exceptionCounter = new AtomicLong(0);
    
    @Autowired(required = false)
    private ExceptionService exceptionService;
    
    /**
     * 记录异常
     * 
     * @param exception 异常对象
     * @param source 异常来源
     */
    @Async
    public void recordException(Exception exception, String source) {
        recordException(exception, source, null);
    }
    
    /**
     * 记录异常（带请求信息）
     * 
     * @param exception 异常对象
     * @param source 异常来源
     * @param request HTTP请求对象
     */
    @Async
    public void recordException(Exception exception, String source, HttpServletRequest request) {
        try {
            // 增加异常计数
            long currentCount = exceptionCounter.incrementAndGet();
            
            // 构建异常记录
            ExceptionRecord record = buildExceptionRecord(exception, source, request, currentCount);
            
            // 使用异常服务记录
            if (exceptionService != null) {
                exceptionService.recordException(record);
            } else {
                // 如果没有异常服务，只记录到日志
                log.warn("ExceptionService not available, logging exception: [{}] {} - {}", 
                    currentCount, source, exception.getMessage());
            }
            
            // 检查异常频率
            checkExceptionFrequency(currentCount, source);
            
        } catch (Exception e) {
            log.error("记录异常失败: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 构建异常记录
     * 
     * @param exception 异常对象
     * @param source 异常来源
     * @param request HTTP请求对象
     * @param sequence 序列号
     * @return 异常记录
     */
    private ExceptionRecord buildExceptionRecord(Exception exception, String source, 
                                               HttpServletRequest request, long sequence) {
        ExceptionRecord record = new ExceptionRecord();
        
        record.setExceptionId(String.valueOf(sequence));
        record.setExceptionType(exception.getClass().getSimpleName());
        record.setExceptionMessage(exception.getMessage());
        record.setSource(source);
        record.setOccurTime(LocalDateTime.now());
        record.setStackTrace(getStackTrace(exception));
        
        // 设置请求相关信息
        if (request != null) {
            record.setRequestUrl(request.getRequestURI());
            record.setRequestMethod(request.getMethod());
            record.setUserAgent(request.getHeader("User-Agent"));
            record.setUserIp(getClientIp(request));
            record.setRequestParams(request.getQueryString());
        }
        
        // 设置严重级别
        record.setLevel(determineSeverity(exception));
        
        return record;
    }
    
    /**
     * 获取异常堆栈信息
     * 
     * @param exception 异常对象
     * @return 堆栈信息字符串
     */
    private String getStackTrace(Exception exception) {
        if (exception == null) {
            return "";
        }
        
        java.io.StringWriter sw = new java.io.StringWriter();
        java.io.PrintWriter pw = new java.io.PrintWriter(sw);
        exception.printStackTrace(pw);
        return sw.toString();
    }
    
    /**
     * 获取客户端IP地址
     * 
     * @param request HTTP请求对象
     * @return 客户端IP地址
     */
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
    
    /**
     * 确定异常严重级别
     * 
     * @param exception 异常对象
     * @return 严重级别
     */
    private String determineSeverity(Exception exception) {
        if (exception == null) {
            return "UNKNOWN";
        }
        
        String exceptionType = exception.getClass().getSimpleName();
        
        // 高危异常
        if (exceptionType.contains("SQL") || 
            exceptionType.contains("DataAccess") ||
            exceptionType.contains("Security") ||
            exceptionType.contains("NullPointer")) {
            return "HIGH";
        }
        
        // 中等异常
        if (exceptionType.contains("Service") || 
            exceptionType.contains("Runtime") ||
            exceptionType.contains("IllegalState")) {
            return "MEDIUM";
        }
        
        // 低风险异常
        if (exceptionType.contains("Validation") || 
            exceptionType.contains("Parameter") ||
            exceptionType.contains("IllegalArgument")) {
            return "LOW";
        }
        
        // 默认中等
        return "MEDIUM";
    }
    
    /**
     * 检查异常频率
     * 
     * @param currentCount 当前异常数量
     * @param source 异常来源
     */
    private void checkExceptionFrequency(long currentCount, String source) {
        // 每100个异常记录一次警告
        if (currentCount % 100 == 0) {
            log.warn("异常频率告警: 系统已发生 {} 次异常，最新来源: {}", currentCount, source);
        }
        
        // 每1000个异常记录一次错误
        if (currentCount % 1000 == 0) {
            log.error("异常频率严重告警: 系统已发生 {} 次异常，需要紧急处理！最新来源: {}", currentCount, source);
        }
    }
    
    /**
     * 获取异常统计
     * 
     * @return 异常总数
     */
    public long getExceptionCount() {
        return exceptionCounter.get();
    }
    
    /**
     * 重置异常计数器
     */
    public void resetCounter() {
        exceptionCounter.set(0);
        log.info("异常计数器已重置");
    }
    
    /**
     * 检查监控器是否可用
     * 
     * @return 是否可用
     */
    public boolean isAvailable() {
        return exceptionService != null;
    }
}
